#ifndef DEVICE_H
#define DEVICE_H

#include <stdio.h>
#include <atomic>
#include <string>
#include <stdio.h>
#include <thread>
#include <mutex>
#include <map>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <linux/videodev2.h>
#include "mk_media.h"
#include "mk_common.h"
#include "mk_h264_splitter.h"
#include "mk_mediakit.h"
#include "public.h"
#include "libyuv.h"

class CFFVideoFilter;

class Device
{
public:
    Device();
    ~Device();

    //设置设备信息
    void setDeviceParam(const STU_CAMERAINFO &info);

    //任务控制
    void startTask();
    void stopTask();
    void autoReconnect();

    //媒体源操作
    void initMediaSource();
    void releaseMediaSource();

    // 打开摄像头设备 ffmpeg
    AVFormatContext *openCameraInFFmpeg(const char* device_name);
    // 打开摄像头设备 v4l2
    int openCameraInV4l2(const char* device_name);
    // 初始化解码器
    AVCodecContext* createDecoder(AVFormatContext *fmt_ctx);
    // 初始化编码器
    AVCodecContext* createEncoder();
    //转换YUYV422到YUV420P并缩放 输入、输出frame需已有效设置
    int convert_and_scale_yuyv422_to_yuv420p(AVFrame *inFrame, AVFrame **outFrame);

    //线程执行体
    void run();
    //方式1实现:通用平台 cpu ffmpeg采集 + ffmpeg转换 + ffmpeg编码
    void runWay1();
    //方式2实现:通用平台 cpu v4l2采集 + ffmpeg转换 + ffmpeg编码
    void runWay2();
    //方式3实现:通用平台 gpu v4l2采集 + ffmpeg转换 + ffmpeg硬件编码
    void runWay3();
    //方式4实现:瑞芯微   gpu v4l2采集 + rga转换 + mpp编码
    void runWay4();
    //方式5实现:其它
    void runWay5();

    //改变水印参数
    bool changeVideoFilter(tm *cur, const std::string &filterText, int fontLeft = 30, int fontTop = 30, int fontSize = 26, char *fontColor = "white", float fontAlpha = 1.0);

public:
    //mk相关接口
    mk_media m_media = nullptr;
    mk_h264_splitter m_splitter = nullptr;
    //设备参数
    STU_PUSHPARAM m_param;

    //运行方式
    //0-rtsp 如rtsp://192.168.1.100:554/app-name/stream-name
    //1-file 如/opt/media/test.mp4
    //10-usb相机 通用平台 cpu ffmpeg采集 + ffmpeg转换 + ffmpeg编码      arm下采用libyuv转换
    //11-usb相机 通用平台 cpu v4l2采集 + ffmpeg转换 + ffmpeg编码        arm下采用libyuv转换
    //12-usb相机 通用平台 gpu v4l2采集 + ffmpeg转换 + ffmpeg硬件编码     arm下采用libyuv转换
    //13-usb相机 瑞芯微   gpu v4l2采集 + rga转换 + mpp编码
    int m_runWay = 10;

    //运行状态 用于逻辑重连
    bool m_isRuning = false;
    //用于IO阻塞超时判断
    int64_t m_curIOTime = 0;

    //启用水印
    bool m_enableFilter = true;
    CFFVideoFilter *m_videoFilter = nullptr;

    //实际输入参数 一般与配置参数一致
    int m_inputWidth = 640;
    int m_inputHeight = 480;
    int m_inputFPS = 30;
    int m_inputFormat = 0;

    //h264裸流测试
    bool m_enableH264File = false;
    FILE *m_h264File = nullptr;
    uint32_t m_h264FileSize = 0;

    //v4l2用户空间缓存 默认8帧
    uint m_frameCount = 8;
    uint m_userBufSize[16] = {0};
    void *m_userBuf[16] = {0};

private:
    //运行标志
    std::atomic<bool> m_bRun;

    //视频fd
    int m_videoFd = -1;

    //任务线程
    std::mutex m_mutex;
    std::thread *m_thread = nullptr;
};

//此类移植自ABLMediaServer 个人贡献此部分代码
class CFFVideoFilter
{
public:
    CFFVideoFilter();
    ~CFFVideoFilter();

    //初始化Filter
    bool StartFilter(AVPixelFormat nAVPixel, int nWidth, int nHeight, int nFrameRate, int nFontSize, char* FontColor, float FontAlpha, int FontLeft, int FontTop);
    //释放Filter
    bool StopFilter();

    //执行水印操作
    bool FilteringFrame(AVFrame *srcFrame);

    bool CopyYUVData(unsigned char* pOutYUVData);

    std::string waterMarkText;        //水印内容
    AVFilterGraph *filter_graph = nullptr;      //过滤器graph
    AVFilterContext *buffersink_ctx = nullptr;  //过滤器上下文
    AVFilterContext *buffersrc_ctx = nullptr;
    AVFilterInOut *filterOutputs = nullptr;     //过滤器IO设置
    AVFilterInOut *filterInputs = nullptr;
    AVFrame *filterFrame = nullptr;			  //水印帧

    //上次时间
    int lastYear = 2025;
    int lastMonth = 1;
    int lastDay = 1;
    int lastHour = 0;
    int lastMinute = 0;
    int lastSec = 0;

    /*
     #水印过滤器 FilterVideo_enable 等于 1开启水印功能 为0时FilterVideo_text字段失效
     filterVideo_enable=0
     #水印文字 为空视为不开启水印 长度不超过64
     filterVideo_text=ABL水印测试123
     #水印字体大小 8、9、12、15、18、20、22、36、48、60
     FilterFontSize=30
     #水印字体颜色  green ,red , blue , yellow ,black , white
     FilterFontColor=red
     #水印字体输出起始x坐标
     FilterFontLeft=5
     #水印字体输出起始y坐标
     FilterFontTop=5
     #水印字体文字透明度 0.1、0.2、0.3 ~ 0.9
     */
    int  nFilterFontSize;
    char  nFilterFontColor[32];
    float nFilterFontAlpha;//透明度
    int  nFilterFontLeft;//x坐标
    int  nFilterFontTop;//y坐标

    volatile bool bRunFlag = false;
    int nYUVPos  ;
    int nYPos  ;
    int nUPos  ;
    int nVPos ;
    int i ;
    int m_nWidth,m_nHeight;
};

#endif // DEVICE_H
